/**
 * @name 02 Paths from ip_input to icmp_error
 * @description Find data-flow paths that lead from ip_input to the first parameter of icmp_error.
 * @kind path-problem
 * @problem.severity warning
 */

import cpp
import semmle.code.cpp.dataflow.DataFlow
import DataFlow::PathGraph

/*
 * The previous iteration of this query found every expression that flows
 * to parameter `n` of `icmp_error`. The most interesting looking results
 * were the ones that started in the function `ip_input` because that is
 * where incoming IP packets are handled. So we restrict `isSource` to only
 * expressions from `ip_input`.
 */

class Config extends DataFlow::Configuration {
  Config() { this = "Paths from ip_input to icmp_error" }

  override predicate isSource(DataFlow::Node source) {
    exists (source.asExpr()) and
    source.getFunction().getName() = "ip_input"
  }

  override predicate isSink(DataFlow::Node sink) {
    // The sink is the zero'th parameter of `icmp_error`: `struct mbuf *n`.
    exists (Parameter p
    | p = sink.asParameter() and
      p.getFunction().getName() = "icmp_error" and
      p.getIndex() = 0)
  }
}

from Config cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select source, source, sink, "Expression flows to icmp_error."
